home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / ClipMirror / clipmirror.cpp next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  15.2 KB  |  448 lines

  1. //-----------------------------------------------------------------------------
  2. // File: ClipMirror.cpp
  3. //
  4. // Desc: This sample shows how to use clip planes to implement a planar mirror.
  5. //       The scene is reflected in a mirror and rendered in a 2nd pass. The
  6. //       corners of the mirrors, together with the camera eye point, are used
  7. //       to define a custom set of clip planes so that the reflected geometry
  8. //       appears only within the mirror's boundaries.
  9. //
  10. //       Note: This code uses the D3D Framework helper library.
  11. //
  12. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  13. //-----------------------------------------------------------------------------
  14. #define STRICT
  15. #include <math.h>
  16. #include <D3DX8.h>
  17. #include "D3DApp.h"
  18. #include "D3DFile.h"
  19. #include "D3DFont.h"
  20. #include "D3DUtil.h"
  21. #include "DXUtil.h"
  22.  
  23.  
  24.  
  25.  
  26. //-----------------------------------------------------------------------------
  27. // Name: struct MIRRORVERTEX
  28. // Desc: Custom mirror vertex type
  29. //-----------------------------------------------------------------------------
  30. struct MIRRORVERTEX
  31. {
  32.     D3DXVECTOR3 p;
  33.     D3DXVECTOR3 n;
  34.     DWORD       color;
  35. };
  36.  
  37. #define D3DFVF_MIRRORVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE)
  38.  
  39.  
  40.  
  41.  
  42. //-----------------------------------------------------------------------------
  43. // Name: class CMyD3DApplication
  44. // Desc: Application class. The base class (CD3DApplication) provides the 
  45. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  46. //       adds functionality specific to this sample program.
  47. //-----------------------------------------------------------------------------
  48. class CMyD3DApplication : public CD3DApplication
  49. {
  50.     CD3DFont*    m_pFont;       // Font for drawing text
  51.     CD3DMesh*    m_pTeapot;     // The teapot object
  52.     D3DXMATRIX   m_matTeapot;   // Teapot's local matrix
  53.  
  54.     LPDIRECT3DVERTEXBUFFER8 m_pMirrorVB;
  55.  
  56.     D3DXVECTOR3  m_vEyePt;      // Vectors defining the camera
  57.     D3DXVECTOR3  m_vLookatPt;
  58.     D3DXVECTOR3  m_vUpVec;
  59.  
  60.     HRESULT RenderMirror();
  61.     HRESULT RenderScene();
  62.  
  63. protected:
  64.     HRESULT OneTimeSceneInit();
  65.     HRESULT InitDeviceObjects();
  66.     HRESULT RestoreDeviceObjects();
  67.     HRESULT InvalidateDeviceObjects();
  68.     HRESULT DeleteDeviceObjects();
  69.     HRESULT Render();
  70.     HRESULT FrameMove();
  71.     HRESULT ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format );
  72.     HRESULT FinalCleanup();
  73.  
  74. public:
  75.     CMyD3DApplication();
  76. };
  77.  
  78.  
  79.  
  80.  
  81. //-----------------------------------------------------------------------------
  82. // Name: WinMain()
  83. // Desc: Entry point to the program. Initializes everything, and goes into a
  84. //       message-processing loop. Idle time is used to render the scene.
  85. //-----------------------------------------------------------------------------
  86. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  87. {
  88.     CMyD3DApplication d3dApp;
  89.  
  90.     if( FAILED( d3dApp.Create( hInst ) ) )
  91.         return 0;
  92.  
  93.     return d3dApp.Run();
  94. }
  95.  
  96.  
  97.  
  98.  
  99. //-----------------------------------------------------------------------------
  100. // Name: CMyD3DApplication()
  101. // Desc: Application constructor. Sets attributes for the app.
  102. //-----------------------------------------------------------------------------
  103. CMyD3DApplication::CMyD3DApplication()
  104. {
  105.     m_strWindowTitle    = _T("ClipMirror: Using D3D Clip Planes");
  106.     m_bUseDepthBuffer   = TRUE;
  107.     m_pFont             = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  108.     m_pTeapot           = new CD3DMesh;
  109.     m_pMirrorVB         = NULL;
  110. }
  111.  
  112.  
  113.  
  114.  
  115. //-----------------------------------------------------------------------------
  116. // Name: OneTimeSceneInit()
  117. // Desc: Called during initial app startup, this function performs all the
  118. //       permanent initialization.
  119. //-----------------------------------------------------------------------------
  120. HRESULT CMyD3DApplication::OneTimeSceneInit()
  121. {
  122.     // Initialize the camera's orientation
  123.     m_vEyePt    = D3DXVECTOR3( 0.0f, 2.0f, -6.5f );
  124.     m_vLookatPt = D3DXVECTOR3( 0.0f, 0.0f,  0.0f );
  125.     m_vUpVec    = D3DXVECTOR3( 0.0f, 1.0f,  0.0f );
  126.  
  127.     return S_OK;
  128. }
  129.  
  130.  
  131.  
  132.  
  133. //-----------------------------------------------------------------------------
  134. // Name: FrameMove()
  135. // Desc: Called once per frame, the call is the entry point for animating
  136. //       the scene.
  137. //-----------------------------------------------------------------------------
  138. HRESULT CMyD3DApplication::FrameMove()
  139. {
  140.     // Set the teapot's local matrix (rotating about the y-axis)
  141.     D3DXMatrixRotationY( &m_matTeapot, m_fTime );
  142.  
  143.     // When the window has focus, let the mouse adjust the camera view
  144.     if( GetFocus() )
  145.     {
  146.         D3DXQUATERNION quat = D3DUtil_GetRotationFromCursor( m_hWnd );
  147.         m_vEyePt.x = 5*quat.y;
  148.         m_vEyePt.y = 5*quat.x;
  149.         m_vEyePt.z = -sqrtf( 50.0f - 25*quat.x*quat.x - 25*quat.y*quat.y );
  150.  
  151.         D3DXMATRIX matView;
  152.         D3DXMatrixLookAtLH( &matView, &m_vEyePt, &m_vLookatPt, &m_vUpVec );
  153.         m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  154.     }
  155.  
  156.     return S_OK;
  157. }
  158.  
  159.  
  160.  
  161.  
  162. //-----------------------------------------------------------------------------
  163. // Name: RenderScene()
  164. // Desc: Renders all objects in the scene.
  165. //-----------------------------------------------------------------------------
  166. HRESULT CMyD3DApplication::RenderScene()
  167. {
  168.     D3DXMATRIX matLocal, matWorldSaved;
  169.     m_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorldSaved );
  170.  
  171.     // Build the local matrix
  172.     D3DXMatrixMultiply( &matLocal, &m_matTeapot, &matWorldSaved );
  173.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matLocal );
  174.  
  175.     // Render the object
  176.     m_pTeapot->Render( m_pd3dDevice );
  177.  
  178.     // Restore the modified render states
  179.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorldSaved );
  180.  
  181.     // Output statistics
  182.     m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  183.     m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  184.  
  185.     return S_OK;
  186. }
  187.  
  188.  
  189.  
  190.  
  191. //-----------------------------------------------------------------------------
  192. // Name: RenderMirror()
  193. // Desc: Renders the scene as reflected in a mirror. The corners of the mirror
  194. //       define a plane, which is used to build the reflection matrix. The
  195. //       scene is rendered with the cull-mode reversed, since all normals in
  196. //       the scene are likewise reflected.
  197. //-----------------------------------------------------------------------------
  198. HRESULT CMyD3DApplication::RenderMirror()
  199. {
  200.     D3DXMATRIX matWorldSaved;
  201.     D3DXMATRIX matReflectInMirror;
  202.     D3DXPLANE  plane;
  203.  
  204.     // Save the world matrix so it can be restored
  205.     m_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorldSaved );
  206.  
  207.     // Get the four corners of the mirror. (This should be dynamic rather than
  208.     // hardcoded.)
  209.     D3DXVECTOR3 a(-1.5f, 1.5f, 3.0f );
  210.     D3DXVECTOR3 b( 1.5f, 1.5f, 3.0f );
  211.     D3DXVECTOR3 c( -1.5f,-1.5f, 3.0f );
  212.     D3DXVECTOR3 d( 1.5f,-1.5f, 3.0f );
  213.  
  214.     // Construct the reflection matrix
  215.     D3DXPlaneFromPoints( &plane, &a, &b, &c );
  216.     D3DXMatrixReflect( &matReflectInMirror, &plane );
  217.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matReflectInMirror );
  218.  
  219.     // Reverse the cull mode (since normals will be reflected)
  220.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  221.  
  222.     // Set the custom clip planes (so geometry is clipped by mirror edges).
  223.     // This is the heart of this sample. The mirror has 4 edges, so there are
  224.     // 4 clip planes, each defined by two mirror vertices and the eye point.
  225.     m_pd3dDevice->SetClipPlane( 0, *D3DXPlaneFromPoints( &plane, &b, &a, &m_vEyePt ) );
  226.     m_pd3dDevice->SetClipPlane( 1, *D3DXPlaneFromPoints( &plane, &d, &b, &m_vEyePt ) );
  227.     m_pd3dDevice->SetClipPlane( 2, *D3DXPlaneFromPoints( &plane, &c, &d, &m_vEyePt ) );
  228.     m_pd3dDevice->SetClipPlane( 3, *D3DXPlaneFromPoints( &plane, &a, &c, &m_vEyePt ) );
  229.     m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 
  230.         D3DCLIPPLANE0 | D3DCLIPPLANE1 | D3DCLIPPLANE2 | D3DCLIPPLANE3 );
  231.  
  232.     // Render the scene
  233.     RenderScene();
  234.  
  235.     // Restore the modified render states
  236.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorldSaved );
  237.     m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00 );
  238.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
  239.  
  240.     // Finally, render the mirror itself (as an alpha-blended quad)
  241.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,   TRUE );
  242.     m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  243.     m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  244.  
  245.     m_pd3dDevice->SetStreamSource( 0, m_pMirrorVB, sizeof(MIRRORVERTEX) );
  246.     m_pd3dDevice->SetVertexShader( D3DFVF_MIRRORVERTEX );
  247.     m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  248.  
  249.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,   FALSE );
  250.  
  251.     return S_OK;
  252. }
  253.  
  254.  
  255.  
  256.  
  257. //-----------------------------------------------------------------------------
  258. // Name: Render()
  259. // Desc: Called once per frame, the call is the entry point for 3d
  260. //       rendering. This function sets up render states, clears the
  261. //       viewport, and renders the scene.
  262. //-----------------------------------------------------------------------------
  263. HRESULT CMyD3DApplication::Render()
  264. {
  265.     // Clear the viewport
  266.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  267.                          0x000000ff, 1.0f, 0L );
  268.  
  269.     // Begin the scene
  270.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  271.     {
  272.         // Render the scene
  273.         RenderScene();
  274.  
  275.         // Render the scene in the mirror
  276.         RenderMirror();
  277.  
  278.         // End the scene.
  279.         m_pd3dDevice->EndScene();
  280.     }
  281.  
  282.     return S_OK;
  283. }
  284.  
  285.  
  286.  
  287.  
  288. //-----------------------------------------------------------------------------
  289. // Name: InitDeviceObjects()
  290. // Desc: Initialize scene objects.
  291. //-----------------------------------------------------------------------------
  292. HRESULT CMyD3DApplication::InitDeviceObjects()
  293. {
  294.     // Initialize the font's internal textures
  295.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  296.  
  297.     // Set up the geometry objects
  298.     if( FAILED( m_pTeapot->Create( m_pd3dDevice, _T("Teapot.x") ) ) )
  299.         return D3DAPPERR_MEDIANOTFOUND;
  300.  
  301.     // Create a square for rendering the mirror
  302.     if( FAILED( m_pd3dDevice->CreateVertexBuffer( 4*sizeof(MIRRORVERTEX),
  303.                                                   D3DUSAGE_WRITEONLY,
  304.                                                   D3DFVF_MIRRORVERTEX,
  305.                                                   D3DPOOL_MANAGED, &m_pMirrorVB ) ) )
  306.         return E_FAIL;
  307.  
  308.     // Initialize the mirror's vertices
  309.     MIRRORVERTEX* v;
  310.     m_pMirrorVB->Lock( 0, 0, (BYTE**)&v, 0 );
  311.     v[0].p = D3DXVECTOR3(-1.5f, 1.5f, 3.0f );
  312.     v[2].p = D3DXVECTOR3(-1.5f,-1.5f, 3.0f );
  313.     v[1].p = D3DXVECTOR3( 1.5f, 1.5f, 3.0f );
  314.     v[3].p = D3DXVECTOR3( 1.5f,-1.5f, 3.0f );
  315.     v[0].n     = v[1].n     = v[2].n     = v[3].n     = D3DXVECTOR3(0.0f,0.0f,-1.0f);
  316.     v[0].color = v[1].color = v[2].color = v[3].color = 0x80ffffff;
  317.     m_pMirrorVB->Unlock();
  318.  
  319.     return S_OK;
  320. }
  321.  
  322.  
  323.  
  324.  
  325. //-----------------------------------------------------------------------------
  326. // Name: RestoreDeviceObjects()
  327. // Desc: Initialize scene objects.
  328. //-----------------------------------------------------------------------------
  329. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  330. {
  331.     m_pFont->RestoreDeviceObjects();
  332.  
  333.     // Set up the geometry objects
  334.     m_pTeapot->RestoreDeviceObjects( m_pd3dDevice );
  335.  
  336.     // Set up the textures
  337.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  338.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  339.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  340.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  341.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  342.  
  343.     // Set miscellaneous render states
  344.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   TRUE );
  345.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
  346.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE );
  347.  
  348.     // Set up the matrices
  349.     D3DXMATRIX matWorld, matView, matProj;
  350.     D3DXMatrixIdentity( &matWorld );
  351.     D3DXMatrixLookAtLH( &matView, &m_vEyePt, &m_vLookatPt, &m_vUpVec );
  352.     FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  353.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f );
  354.     m_pd3dDevice->SetTransform( D3DTS_WORLD,      &matWorld );
  355.     m_pd3dDevice->SetTransform( D3DTS_VIEW,       &matView );
  356.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  357.  
  358.     // Set up a light
  359.     if( ( m_d3dCaps.VertexProcessingCaps & D3DVTXPCAPS_DIRECTIONALLIGHTS ) ||
  360.        !( m_dwCreateFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) )
  361.     {
  362.         D3DLIGHT8 light;
  363.         D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.2f, -1.0f, -0.2f );
  364.         m_pd3dDevice->SetLight( 0, &light );
  365.         m_pd3dDevice->LightEnable( 0, TRUE );
  366.     }
  367.     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xff555555 );
  368.  
  369.     return S_OK;
  370. }
  371.  
  372.  
  373.  
  374.  
  375. //-----------------------------------------------------------------------------
  376. // Name: InvalidateDeviceObjects()
  377. // Desc:
  378. //-----------------------------------------------------------------------------
  379. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  380. {
  381.     m_pFont->InvalidateDeviceObjects();
  382.     m_pTeapot->InvalidateDeviceObjects();
  383.  
  384.     return S_OK;
  385. }
  386.  
  387.  
  388.  
  389.  
  390. //-----------------------------------------------------------------------------
  391. // Name: DeleteDeviceObjects()
  392. // Desc: Called when the app is exiting, or the device is being changed,
  393. //       this function deletes any device dependent objects.
  394. //-----------------------------------------------------------------------------
  395. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  396. {
  397.     m_pFont->DeleteDeviceObjects();
  398.     m_pTeapot->Destroy();
  399.  
  400.     SAFE_RELEASE( m_pMirrorVB );
  401.  
  402.     return S_OK;
  403. }
  404.  
  405.  
  406.  
  407.  
  408. //-----------------------------------------------------------------------------
  409. // Name: ConfirmDevice()
  410. // Desc: Called during device intialization, this code checks the device
  411. //       for some minimum set of capabilities
  412. //-----------------------------------------------------------------------------
  413. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  414.                                           D3DFORMAT Format )
  415. {
  416.     if( dwBehavior & D3DCREATE_PUREDEVICE )
  417.         return E_FAIL; // GetTransform doesn't work on PUREDEVICE
  418.  
  419.     if( ( dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
  420.         ( dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )
  421.     {
  422.         if( pCaps->MaxUserClipPlanes < 4 )
  423.             return E_FAIL;
  424.     }
  425.  
  426.     return S_OK;
  427. }
  428.  
  429.  
  430.  
  431.  
  432. //-----------------------------------------------------------------------------
  433. // Name: FinalCleanup()
  434. // Desc: Called before the app exits, this function gives the app the chance
  435. //       to cleanup after itself.
  436. //-----------------------------------------------------------------------------
  437. HRESULT CMyD3DApplication::FinalCleanup()
  438. {
  439.     SAFE_DELETE( m_pFont );
  440.     SAFE_DELETE( m_pTeapot );
  441.  
  442.     return S_OK;
  443. }
  444.  
  445.  
  446.  
  447.  
  448.